/*
	一个简单的todo list管理工具，可以添加和删除todo list项目
	code by 侯佩|hopy , copyright @ 2015.07.28
*/

#import <Foundation/Foundation.h>
#import <gtk/gtk.h>

//GtkWidget常量定义
#define UI_PATH "./clist.ui"
#define TOP_WINDOW "window"
#define TREE_VIEW "tree_view"
#define SCROLLED_WIN "scrolled_window"
#define INPUT_ENTRY "entry"
#define COL_DATE_BOX "col_date_box"
//#define BTN_ADD "btn_add"
#define BTN_REMOVE "btn_remove"

//GtkWidget全局变量定义
static GtkWidget *s_tv;
static GtkWidget *s_entry;
static GtkWidget *s_col_date_box;
static GArray *s_notes = NULL;
//static GtkWidget *s_btn_add;
static GtkWidget *s_btn_remove;

static const char *str_now(void);

typedef struct {
	gchar *date;
	gchar *note;
}item_t,*pitem_t;

enum
{
	COLUMN_ITEM_DATE,
	COLUMN_ITEM_NOTE,
	NUM_ITEM_COLUMNS
};

//GtkTreeView选中行发生变化时回调
void row_activated_handle(GtkTreeView *tv,gpointer user_data){
	NSLog(@"%s:enter!",__func__);
	GtkTreeIter iter;
	GtkTreeSelection *selection = gtk_tree_view_get_selection(tv);

	//如果tv有行被选中则将btn_remove启用，否则将其禁用
	if(gtk_tree_selection_get_selected(selection,NULL,&iter)){
		NSLog(@"%s:something is selected!",__func__);
		gtk_widget_set_sensitive(s_btn_remove,TRUE);
	}else{
		NSLog(@"%s:nothing is selected!",__func__);
		gtk_widget_set_sensitive(s_btn_remove,FALSE);
	}
}

//btn_quit按钮按下时调用
void quit_handle(GtkWidget *self,gpointer user_data){
	gtk_widget_destroy(GTK_WIDGET(user_data));
}

//btn_remove按钮按下时调用
void remove_handle(GtkWidget *self,gpointer user_data){
	GtkTreeIter iter;
	GtkTreeView *tv = GTK_TREE_VIEW(user_data);
	GtkTreeModel *model = gtk_tree_view_get_model(tv);
	GtkTreeSelection *selection = gtk_tree_view_get_selection(tv);

	//如果tv有行被选中则删除显示且更新model
	if(gtk_tree_selection_get_selected(selection,NULL,&iter)){
		gint i;
		//从选中列获取model中的path
		GtkTreePath *path = gtk_tree_model_get_path(model,&iter);
		//取得path的序号
		i = gtk_tree_path_get_indices(path)[0];
		//删除视图中选中行
		gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
		//删除model中的数据
		g_array_remove_index(s_notes,i);
		gtk_tree_path_free(path);
	}
}

void add_handle(GtkWidget *self,gpointer user_data){
	item_t item;
	GtkTreeIter current,iter;
	GtkTreePath *path;
	GtkTreeModel *model;
	GtkTreeViewColumn *col;
	GtkTreeView *tv = GTK_TREE_VIEW(user_data);

	g_return_if_fail(s_notes != NULL);
	const gchar *text = gtk_entry_get_text(GTK_ENTRY(s_entry));
	NSLog(@"%s:%s",__func__,text);

	item.date = g_strdup(str_now());
	item.note = g_strdup(text);
	//如果输入框为空直接返回
	if(strlen(item.note) == 0){
		return;
	}
	g_array_append_vals(s_notes,&item,1);

	model = gtk_tree_view_get_model(tv);
	//取得tv中当前光标选中行
	gtk_tree_view_get_cursor(tv,&path,NULL);
	//如果当前没有光标选中行则插在第一行，否则插在选中行下面一行
	if(!path){
		gtk_list_store_insert_after(GTK_LIST_STORE(model),&iter,NULL);
	}else{
		//int i = gtk_tree_path_get_indices(path)[0];
		gtk_tree_model_get_iter(model,&current,path);
		gtk_tree_path_free(path);
		gtk_list_store_insert_after(GTK_LIST_STORE(model),&iter,&current);
	}

	gtk_list_store_set(GTK_LIST_STORE(model),&iter,COLUMN_ITEM_DATE,item.date,
		COLUMN_ITEM_NOTE,item.note,-1);
	path = gtk_tree_model_get_path(model,&iter);
	col = gtk_tree_view_get_column(tv,0);
	gtk_tree_view_set_cursor(tv,path,col,FALSE);
	gtk_tree_path_free(path);
}

static const char *str_now(void){
	static gchar buf[256];
	time_t now;
	time(&now);
	struct tm *time_info = localtime(&now);
	strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",time_info);
	return (const char*)buf;
}
/*
static const char *str_now_objc(void){
	NSDate *now = [NSDate date];
	NSDateFormatter *ft = [NSDateFormatter new];
	//ft.dateStyle = NSDateFormatterFullStyle;
	ft.dateFormat = @"yyyy-MM-dd kk:mm:ss zzz";
	//[ft setDateFormat:@"yyyy"];
	ft.timeZone = [NSTimeZone timeZoneWithName:@"GMT+8"];
	NSString *str = [ft stringFromDate:now];
	//char *buf = malloc(str.length);
	//strncpy(buf,str.UTF8String,str.length);
	NSLog(@"%s:%@",__func__,str);
	return str.UTF8String;
}
*/

static void add_items(void){
	item_t item;
	g_return_if_fail(s_notes != NULL);
	
	item.date = g_strdup(str_now());
	item.note = g_strdup("say:hello world!");
	g_array_append_vals(s_notes,&item,1);

	item.date = g_strdup(str_now());
	item.note = g_strdup("write:do some coding...");
	g_array_append_vals(s_notes,&item,1);
}

static GtkTreeModel *create_items_model(void){
	GtkListStore *model;
	GtkTreeIter iter;

	s_notes = g_array_sized_new(FALSE,FALSE,sizeof(item_t),1);
	add_items();

	model = gtk_list_store_new(NUM_ITEM_COLUMNS,G_TYPE_STRING,G_TYPE_STRING);
	for(gint i = 0;i<s_notes->len;i++){
		gtk_list_store_append(model,&iter);
		gtk_list_store_set(model,&iter,\
			COLUMN_ITEM_DATE,g_array_index(s_notes,item_t,i).date,\
			COLUMN_ITEM_NOTE,g_array_index(s_notes,item_t,i).note,-1);
	}

	return GTK_TREE_MODEL(model);																				
}
		
static void cell_edited(GtkCellRendererText *cell,const gchar *path_string,const gchar *new_text,
	gpointer user_data){
	GtkTreeModel *model = GTK_TREE_MODEL(user_data);
	GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
	GtkTreeIter iter;
	gint col = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell),"column"));
	gtk_tree_model_get_iter(model,&iter,path);
	switch(col){
		case COLUMN_ITEM_NOTE:
		{
			gchar *old_text;
			gtk_tree_model_get(model,&iter,col,&old_text,-1);
			g_free(old_text);

			gint i = gtk_tree_path_get_indices(path)[0];
			g_free(g_array_index(s_notes,item_t,i).note);
			g_array_index(s_notes,item_t,i).note = g_strdup(new_text);
			gtk_list_store_set(GTK_LIST_STORE(model),&iter,col,
				g_array_index(s_notes,item_t,i).note,-1);
		}
		break;
	}
	gtk_tree_path_free(path);
}

void add_cols(GtkTreeView *tv,GtkTreeModel *model){
	GtkCellRenderer *r;
	r = gtk_cell_renderer_text_new();
	g_object_set(r,"editable",FALSE,NULL);
	g_object_set_data(G_OBJECT(r),"column",GINT_TO_POINTER(COLUMN_ITEM_DATE));
	//gtk_tree_view_insert_column_with_attributes(tv,-1,"Date",r,"text",COLUMN_ITEM_DATE,NULL);
	//GtkTreeViewColumn *tv_col = gtk_tree_view_column_new();
	GtkTreeViewColumn *tv_col = gtk_tree_view_column_new_with_attributes("Date",r,"text",
		COLUMN_ITEM_DATE,NULL);
	printf("%s:%p\n",__func__,s_col_date_box);
	//gtk_tree_view_column_add_attribute(tv_col,r,"text",COLUMN_ITEM_DATE);
	//gtk_tree_view_column_set_attributes(tv_col,r,"text",COLUMN_ITEM_DATE,NULL);

	gtk_tree_view_column_set_widget(tv_col,s_col_date_box);
	gtk_tree_view_column_set_resizable(tv_col,TRUE);
	gtk_tree_view_insert_column(GTK_TREE_VIEW(tv),tv_col,-1);

	r = gtk_cell_renderer_text_new();
	g_object_set(r,"editable",TRUE,NULL);
	g_signal_connect(r,"edited",G_CALLBACK(cell_edited),model);
	g_object_set_data(G_OBJECT(r),"column",GINT_TO_POINTER(COLUMN_ITEM_NOTE));
	gint col_idx = gtk_tree_view_insert_column_with_attributes(tv,-1,"Note",r,"text",
		COLUMN_ITEM_NOTE,NULL);
	GtkTreeViewColumn *col = gtk_tree_view_get_column(tv,col_idx-1);
	gtk_tree_view_column_set_sort_column_id(col,COLUMN_ITEM_NOTE);
}

int main(int argc,char **argv){
	@autoreleasepool{
		GtkWidget *w;
		GtkWidget *scrolled_win;
		GError *error = NULL;
		GtkTreeModel *model;

		gtk_init(&argc,&argv);
		GtkBuilder *builder = gtk_builder_new();
		if(!gtk_builder_add_from_file(builder,UI_PATH,&error)){
			g_critical("Couldn't load builder file: %s",error->message);
			g_error_free(error);
		}

		w = GTK_WIDGET(gtk_builder_get_object(builder,TOP_WINDOW));
		if(!w){
			g_critical("Widget \"%s\" is missing in file %s",TOP_WINDOW,UI_PATH);
		}
		gtk_window_set_title(GTK_WINDOW(w),"clist todo list");
		gtk_window_set_default_size(GTK_WINDOW(w),600,400);
		gtk_window_set_position(GTK_WINDOW(w),GTK_WIN_POS_CENTER_ALWAYS);
		gtk_container_set_border_width(GTK_CONTAINER(w),5);

		scrolled_win = GTK_WIDGET(gtk_builder_get_object(builder,SCROLLED_WIN));
		s_tv = GTK_WIDGET(gtk_builder_get_object(builder,TREE_VIEW));
		gtk_widget_set_size_request(GTK_WIDGET(scrolled_win),600,330);
		gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(s_tv),GTK_TREE_VIEW_GRID_LINES_BOTH);
		//gtk_tree_view_columns_autosize(GTK_TREE_VIEW(s_tv));

		s_entry = GTK_WIDGET(gtk_builder_get_object(builder,INPUT_ENTRY));
		s_col_date_box = GTK_WIDGET(gtk_builder_get_object(builder,COL_DATE_BOX));
		//gtk_widget_set_size_request(GTK_WIDGET(s_tv),600,400);

		model = create_items_model();
		gtk_tree_view_set_model(GTK_TREE_VIEW(s_tv),model);
		gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(s_tv)),
			GTK_SELECTION_SINGLE);
		add_cols(GTK_TREE_VIEW(s_tv),model);

		//s_btn_add = GTK_WIDGET(gtk_builder_get_object(builder,BTN_ADD));
		s_btn_remove = GTK_WIDGET(gtk_builder_get_object(builder,BTN_REMOVE));
		NSLog(@"%s:s_btn_remove %p",__func__,s_btn_remove);
		gtk_widget_set_sensitive(s_btn_remove,FALSE);

		gtk_builder_connect_signals(builder,NULL);
		g_object_unref(builder);

		gtk_widget_show_all(w);
		gtk_main();
	}
	return 0;
}